package com.lanhai.crowd.mvc.config;

import com.google.gson.Gson;
import com.lanhai.crowd.constant.CrowdConstant;
import com.lanhai.crowd.exception.AccessForbiddenException;
import com.lanhai.crowd.exception.LoginAcctAlreadyInUseException;
import com.lanhai.crowd.exception.LoginAcctAlreadyInUseForUpdateException;
import com.lanhai.crowd.exception.LoginFailedException;
import com.lanhai.crowd.util.CrowdUtil;
import com.lanhai.crowd.util.ResultEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @ControllerAdvice表示当前类是一个基于注解的异常处理类
 */
@ControllerAdvice
public class CrowdExceptionResolver {




    /**
     *
     * @param exception 用户名重复异常
     * @param req
     * @param resp
     * @return 新增用户页面
     * @throws IOException
     */
    @ExceptionHandler(value = LoginAcctAlreadyInUseException.class)
    public ModelAndView resolveLoginAcctAlreadyInUseException(
            LoginAcctAlreadyInUseException exception, HttpServletRequest req,
            HttpServletResponse resp) throws IOException {

        return commonResolve("admin-add", exception, req, resp);

    }

    /**
     * 没啥用，因为前台不让修改用户名
     * @param exception 修改时用户名重复异常
     * @param req
     * @param resp
     * @return 新增用户页面
     * @throws IOException
     */
    @ExceptionHandler(value = LoginAcctAlreadyInUseForUpdateException.class)
    public ModelAndView resolveLoginAcctAlreadyInUseForUpdateException(
            LoginAcctAlreadyInUseForUpdateException exception, HttpServletRequest req,
            HttpServletResponse resp) throws IOException {

        return commonResolve("system-error", exception, req, resp);

    }


    /**
     *
     * @param exception 未登录异常
     * @param req
     * @param resp
     * @return 登录页面
     * @throws IOException
     */
    @ExceptionHandler(value = AccessForbiddenException.class)
    public ModelAndView resolveAccessForbiddenException(
            AccessForbiddenException exception, HttpServletRequest req,
            HttpServletResponse resp) throws IOException {

        return commonResolve("admin-login", exception, req, resp);

    }

    /**
     *
     * @param exception 登录异常
     * @param req
     * @param resp
     * @return 登录页面
     * @throws IOException
     */
    @ExceptionHandler(value = LoginFailedException.class)
    public ModelAndView resolveLoginFailedException(
            LoginFailedException exception, HttpServletRequest req,
            HttpServletResponse resp) throws IOException {

        return commonResolve("admin-login", exception, req, resp);

    }

    /**
     *
     * @param exception 算数异常
     * @param req
     * @param resp
     * @return
     * @throws IOException
     */
    @ExceptionHandler(value = ArithmeticException.class)
    public ModelAndView resolveArithmeticException(
            ArithmeticException exception, HttpServletRequest req,
            HttpServletResponse resp) throws IOException {

        return commonResolve("system-error", exception, req, resp);

    }

    /**
     * @param exception
     * @return
     * @ExceptionHandler 将一个具体的异常类型和一个方法关联
     */
    @ExceptionHandler(value = NullPointerException.class)
    public ModelAndView resolveNullPointException(
            NullPointerException exception, HttpServletRequest req,
            HttpServletResponse resp) throws IOException {

        return commonResolve("system-error", exception, req, resp);

    }

    /**
     * 异常处理通用代码
     * @param pageName 返回页面名
     * @param exception 异常类型
     * @param req       请求对象
     * @param resp      相应对象
     * @return
     * @throws IOException
     */
    private ModelAndView commonResolve(
            String pageName, Exception exception,
            HttpServletRequest req, HttpServletResponse resp) throws IOException {
        // 1.判断请求类型
        boolean requestType = CrowdUtil.jundgeRequestType(req);

        // 2.如果是AJAX请求
        if (requestType) {

            // 3.创建ResultEntity对象
            ResultEntity<Object> resultEntity = ResultEntity.error(exception.getMessage());

            // 4.创建Gson对象
            Gson gson = new Gson();

            // 5.将ResultEntity对象转换成Json字符串
            String json = gson.toJson(resultEntity);

            // 6.将JSON字符串作为相应体返回给浏览器
            resp.getWriter().write(json);

            // 7.由于上面已经通过resp对象返回了相应，所以不提供ModelAndView对象
            return null;
        }

        // 8.如果不是AJAX请求，则创建ModelAndView对象
        ModelAndView modelAndView = new ModelAndView();

        // 9.将Exception对象存入模型
        modelAndView.addObject(CrowdConstant.ATTR_NAME_EXCEPTION, exception);

        // 10.设置对应的视图名称
        modelAndView.setViewName(pageName);

        // 11.返回ModelAndView对象
        return modelAndView;


    }
}
